package com.thfw.test.view.activity;

import android.Manifest;
import android.app.AlertDialog;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.Bundle;

import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ExpandableListView;
import android.widget.GridLayout;
import android.widget.GridView;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.SimpleExpandableListAdapter;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import com.thfw.wmd.R;
import com.thfw.test.utils.BluetoothDeviceManager;
import com.thfw.test.utils.HexUtil;
import com.thfw.test.utils.ToastUtil;
import com.thfw.test.utils.WifiAutoConnectManager;
import com.thfw.test.view.ViseBle;
import com.thfw.test.view.adapter.MergeAdapter;
import com.thfw.test.view.adapter.WifiListAdapter;
import com.thfw.test.view.callback.IBleCallback;
import com.thfw.test.view.common.BluetoothServiceType;
import com.thfw.test.view.common.ConnectState;
import com.thfw.test.view.common.PropertyType;
import com.thfw.test.view.core.BluetoothGattChannel;
import com.thfw.test.view.core.DeviceMirror;
import com.thfw.test.view.event.CallbackDataEvent;
import com.thfw.test.view.event.ConnectEvent;
import com.thfw.test.view.event.NotifyDataEvent;
import com.thfw.test.view.exception.BleException;
import com.thfw.test.view.model.BluetoothLeDevice;
import com.thfw.test.view.model.resolver.GattAttributeResolver;
import com.vise.xsnow.cache.SpCache;
import com.vise.xsnow.event.BusManager;
import com.vise.xsnow.event.Subscribe;
import com.wang.avi.AVLoadingIndicatorView;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;


import utils.AppActivities;

import static com.thfw.test.utils.WifiAutoConnectManager.WifiCipherType.WIFICIPHER_NOPASS;
import static com.thfw.test.utils.WifiAutoConnectManager.WifiCipherType.WIFICIPHER_WEP;
import static com.thfw.test.utils.WifiAutoConnectManager.WifiCipherType.WIFICIPHER_WPA;
import static com.thfw.test.view.activity.DeviceDetailActivity.EXTRA_DEVICE;

/**
 * 设备数据操作相关展示界面
 */
public class DeviceControlActivity extends AppCompatActivity {

    private static final String LIST_NAME = "NAME";
    private static final String LIST_UUID = "UUID";
    public static final String WRITE_CHARACTERISTI_UUID_KEY = "write_uuid_key";
    public static final String NOTIFY_CHARACTERISTIC_UUID_KEY = "notify_uuid_key";
    public static final String WRITE_DATA_KEY = "write_data_key";

    public static SimpleExpandableListAdapter simpleExpandableListAdapter;
    private TextView mConnectionState;
    private TextView mGattUUID;
    private TextView mGattUUIDDesc;
    private TextView mDataAsString;
    private TextView mDataAsArray;
    private EditText mInput;
    private EditText mOutput;
    AVLoadingIndicatorView avi;
    private SpCache mSpCache;
    private GridLayout gl_msg;
    TextView ed_wifiname;
    RelativeLayout rl_background;
    RelativeLayout rl_historyCB;
    EditText password;
    TextView tv_label;
    Button ok;
    private AlertDialog.Builder builder;
    private AlertDialog alertDialog;
    ArrayList<ScanResult> list;
    LayoutInflater inflater;
    View layout;
    ListView myListView;
    ImageButton myImageButtion;
    Timer timer;
    TimerTask timerTask;
    private boolean isLoading = true;
    WifiManager mWifiManager;
    private WifiAutoConnectManager mWifiAutoConnectManager;
    public static final int WIFI_SCAN_PERMISSION_CODE = 2;
    private WifiListAdapter adapter;
    private int networkid = -1;
    public String ssid;
    boolean isLinked = false;
    WifiAutoConnectManager.WifiCipherType type = WIFICIPHER_NOPASS;
    final Handler handler = new Handler(msg -> {
        switch (msg.what) {
            case 1:
                scanWifiInfo();
                break;
            default:
                break;
        }
        return false;
    });

    //设备信息
    private BluetoothLeDevice mDevice;
    //输出数据展示
    private StringBuilder mOutputInfo = new StringBuilder();
    private List<BluetoothGattService> mGattServices = new ArrayList<>();
    //设备特征值集合
    private List<List<BluetoothGattCharacteristic>> mGattCharacteristics = new ArrayList<>();

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_device_control);
        BusManager.getBus().register(this);
        mDevice = getIntent().getParcelableExtra(EXTRA_DEVICE);
        init();
        initWifi();


    }

    private void init() {
        appendDeviceInfo(null,mDevice);
        mConnectionState = findViewById(R.id.connection_state);
        mGattUUID = findViewById(R.id.uuid);
        mGattUUIDDesc = findViewById(R.id.description);
        mDataAsString = findViewById(R.id.data_as_string);
        mDataAsArray = findViewById(R.id.data_as_array);
        mInput = findViewById(R.id.input);
        mOutput = findViewById(R.id.output);
        ok = findViewById(R.id.ok);
        avi = findViewById(R.id.avi);
        gl_msg = findViewById(R.id.gl_msg);
        password = findViewById(R.id.password);
        rl_background= findViewById(R.id.rl_background);
        rl_historyCB = findViewById(R.id.rl_historyCB);
        ed_wifiname = findViewById(R.id.ed_wifiname);
        mDevice = getIntent().getParcelableExtra(EXTRA_DEVICE);
        if (mDevice != null) {
            ((TextView) findViewById(R.id.device_address)).setText(mDevice.getAddress());
        }

        mSpCache = new SpCache(this);

        findViewById(R.id.select_write_characteristic).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showGattServices();
            }
        });
        findViewById(R.id.select_notify_characteristic).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showGattServices();
            }
        });
        findViewById(R.id.select_read_characteristic).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showGattServices();
            }
        });
        findViewById(R.id.send).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mInput.getText() == null || mInput.getText().toString() == null) {
                    ToastUtil.showToast(DeviceControlActivity.this, "Please input command!");
                    return;
                }
                if (!isHexData(mInput.getText().toString())) {
                    ToastUtil.showToast(DeviceControlActivity.this, "Please input hex data command!");
                    return;
                }
                mSpCache.put(WRITE_DATA_KEY + mDevice.getAddress(), mInput.getText().toString());

                try{
                    BluetoothDeviceManager.getInstance().write(mDevice, HexUtil.decodeHex(mInput.getText().toString().toCharArray()));
                }catch (RuntimeException e){
                    Toast.makeText(DeviceControlActivity.this,"请检查输入内容，转换16进制数据失败",Toast.LENGTH_SHORT).show();
                }


            }
        });

        inflater = (LayoutInflater) this.getSystemService(LAYOUT_INFLATER_SERVICE);
        layout = inflater.inflate(R.layout.formcommonlist, null);

        myListView = layout.findViewById(R.id.formcustomspinner_list);
        myImageButtion = layout.findViewById(R.id.btn_reload);
        tv_label = layout.findViewById(R.id.tv_label);
        ed_wifiname.setOnClickListener(v ->
                showDialog());
        myImageButtion.setOnClickListener(v -> {
            if (isLoading) {
                resetTask();
                myImageButtion.setBackgroundResource(R.mipmap.reload);
                isLoading = false;
                tv_label.setText(R.string.stop_reload);
            } else {
                startTimerTask();
                myImageButtion.setBackgroundResource(R.mipmap.stop);
                isLoading = true;
                tv_label.setText(R.string.select_reload);
            }

        });
        rl_background.setOnClickListener(v -> {
            InputMethodManager manager = ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE));
            manager.hideSoftInputFromWindow(ed_wifiname.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
        });
        list = new ArrayList<>();
        adapter = new WifiListAdapter(this, list);
        myListView.setAdapter(adapter);
        myListView.setOnItemClickListener((arg0, arg1, positon, id) -> {

            if (alertDialog != null) {
                alertDialog.dismiss();
                resetTask();
            }
            ed_wifiname.setText(((ScanResult) adapter.getItem(positon)).SSID);
            ssid = ((ScanResult) adapter.getItem(positon)).SSID;
//            type = WifiAutoConnectManager.getCipherType(ssid);
            String capabilities = ((ScanResult) adapter.getItem(positon)).capabilities;
            if (!TextUtils.isEmpty(capabilities)) {
                if (capabilities.contains("WPA") || capabilities.contains("wpa")) {
                    type = WIFICIPHER_WPA;
                } else if (capabilities.contains("WEP") || capabilities.contains("wep")) {
                    type = WIFICIPHER_WEP;
                } else {
                    type = WIFICIPHER_NOPASS;
                }
            }

        });
        ok.setOnClickListener(v -> {

            try{
                BluetoothDeviceManager.getInstance().write(mDevice, HexUtil.decodeHex(stringToASCII(ssid, password.getText().toString())));
                Toast.makeText(this,"设备网络连接成功",Toast.LENGTH_SHORT).show();
            }catch (RuntimeException e){
                Toast.makeText(this,"请检查输入内容，转换16进制数据失败",Toast.LENGTH_SHORT).show();
            }



        });
        builder = new AlertDialog.Builder(this);
        builder.setView(layout);
        alertDialog = builder.create();

    }

    public static String stringToASCII(String ssid, String password) {//字符串转换为ASCII码

        char[] chars1 = ssid.toCharArray(); //把字符中转换为字符数组
        char[] chars2 = password.toCharArray(); //把字符中转换为字符数组

        StringBuilder s1 = new StringBuilder();
        s1.append("BEEF").append("81");
        StringBuilder s2 = new StringBuilder();
        StringBuilder s3 = new StringBuilder();
        for (int i = 0; i < chars1.length; i++) {//输出结果
            s2.append((int) chars1[i]);
        }
        for (int i = 0; i < chars2.length; i++) {//输出结果
            s3.append((int) chars2[i]);
        }
        String length = Integer.toHexString(ssid.length() + password.length()+2);
        StringBuilder s= new StringBuilder();
        if(length.length()==1){
            s.append(0);
            s.append(length);
        }else{
            s.append(length);
        }
        s1.append(length).append(HexUtil.encodeHexStr(ssid.getBytes())).append("2C")
                .append(HexUtil.encodeHexStr(password.getBytes()));
        int num = HexUtil.get_crc( s1.toString() , s1.toString().getBytes().length);
        s1.append(Integer.toHexString(num)).append("FEEB");
        return s1.toString();
    }






    static int getCrc(StringBuilder s,int length){
         int i;
         int  result = 0;

        for(i = 0; i < length; i++){
            result = result ^ s.charAt(i);
        }
        return result;
    }

    public void showDialog() {

        alertDialog.show();
        mWifiManager.startScan();
        startTimerTask();
    }



    /**
     * 初始化wifi操作
     */
    void scanWifiInfo() {

        List<ScanResult> mWifiList;
        if (!mWifiManager.isWifiEnabled()) {
            mWifiManager.setWifiEnabled(true);
        }
        mWifiList = mWifiManager.getScanResults();
        adapter.setListAll(mWifiList);
    }

    void startTimerTask() {
        if (timer == null) {
            timer = new Timer();
        }
        if (timerTask == null) {
            timerTask = new TimerTask() {
                @Override
                public void run() {
                    handler.sendEmptyMessage(1);
                }
            };

        }
        timer.schedule(timerTask, 1000, 3 * 1000);
    }

    void resetTask() {
        if (timer != null) {
            timer.cancel();
        }
        if (timerTask != null) {
            timerTask.cancel();
        }
        timerTask = null;
        timer = null;
    }

    void initWifi(){
        mWifiManager = (WifiManager)getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        mWifiAutoConnectManager = WifiAutoConnectManager.newInstance(mWifiManager);
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // 获取wifi连接需要定位权限,没有获取权限
            ActivityCompat.requestPermissions(this, new String[]{
                    Manifest.permission.ACCESS_COARSE_LOCATION,
            }, WIFI_SCAN_PERMISSION_CODE);
            return;
        }
        //获取并展示当前连接的wifi
        if (mWifiManager != null) {
            if(mWifiManager.getConnectionInfo()!=null){
                ed_wifiname.setText(mWifiManager.getConnectionInfo().getSSID());
            }else{

            }
        }
        checkNetWorkState();
    }
    @Subscribe
    public void showConnectedDevice(ConnectEvent event) {
        if (event != null) {
            if (event.isSuccess()) {
                ToastUtil.showToast(DeviceControlActivity.this, "连接成功");
                mConnectionState.setText("true");
                avi.hide();
                invalidateOptionsMenu();
                if (event.getDeviceMirror() != null && event.getDeviceMirror().getBluetoothGatt() != null) {
                    simpleExpandableListAdapter = displayGattServices(event.getDeviceMirror().getBluetoothGatt().getServices());
                }
                gl_msg.setVisibility(View.GONE);
                avi.setVisibility(View.GONE);
                rl_background.setVisibility(View.VISIBLE);
            } else {
                if (event.isDisconnected()) {
                    ToastUtil.showToast(DeviceControlActivity.this, "已经有存在的连接");
                } else {
                    ToastUtil.showToast(DeviceControlActivity.this, "连接失败");
                }
                avi.hide();
                mConnectionState.setText("false");
                invalidateOptionsMenu();
                clearUI();
            }
        }
    }

    @Subscribe
    public void showDeviceCallbackData(CallbackDataEvent event) {
        if (event != null) {
            if (event.isSuccess()) {
                if (event.getBluetoothGattChannel() != null && event.getBluetoothGattChannel().getCharacteristic() != null
                        && event.getBluetoothGattChannel().getPropertyType() == PropertyType.PROPERTY_READ) {
                    showReadInfo(event.getBluetoothGattChannel().getCharacteristic().getUuid().toString(), event.getData());
                }
            } else {
                ((EditText) findViewById(R.id.show_write_characteristic)).setText("");
                ((EditText) findViewById(R.id.show_notify_characteristic)).setText("");
            }
        }
    }

    @Subscribe
    public void showDeviceNotifyData(NotifyDataEvent event) {
        if (event != null && event.getData() != null && event.getBluetoothLeDevice() != null
                && event.getBluetoothLeDevice().getAddress().equals(mDevice.getAddress())) {
            mOutputInfo.append(HexUtil.encodeHexStr(event.getData())).append("\n");
            mOutput.setText(mOutputInfo.toString());
        }
    }
    @Override
    protected void onResume() {
        invalidateOptionsMenu();
        super.onResume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        resetTask();
    }



    @Override
    public boolean onCreateOptionsMenu(final Menu menu) {
        getMenuInflater().inflate(R.menu.connect, menu);
        if (BluetoothDeviceManager.getInstance().isConnected(mDevice)) {
            menu.findItem(R.id.menu_connect).setVisible(false);
            menu.findItem(R.id.menu_disconnect).setVisible(true);
            mConnectionState.setText("true");
            DeviceMirror deviceMirror = ViseBle.getInstance().getDeviceMirror(mDevice);
            if (deviceMirror != null) {
                simpleExpandableListAdapter = displayGattServices(deviceMirror.getBluetoothGatt().getServices());
            }
            showDefaultInfo();
        } else {
            menu.findItem(R.id.menu_connect).setVisible(true);
            menu.findItem(R.id.menu_disconnect).setVisible(false);
            mConnectionState.setText("false");
            clearUI();
        }
        if (ViseBle.getInstance().getConnectState(mDevice) == ConnectState.CONNECT_PROCESS) {
            menu.findItem(R.id.menu_refresh).setActionView(R.layout.actionbar_progress_indeterminate);
        } else {
            menu.findItem(R.id.menu_refresh).setActionView(null);
        }
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(final MenuItem item) {
        switch (item.getItemId()) {
            case R.id.menu_connect://连接设备
                if (!BluetoothDeviceManager.getInstance().isConnected(mDevice)) {
                    BluetoothDeviceManager.getInstance().connect(mDevice);
                    invalidateOptionsMenu();
                    avi.show();
                }
                break;
            case R.id.menu_disconnect://断开设备
                if (BluetoothDeviceManager.getInstance().isConnected(mDevice)) {
                    BluetoothDeviceManager.getInstance().disconnect(mDevice);
                    invalidateOptionsMenu();
                    gl_msg.setVisibility(View.VISIBLE);
                    avi.setVisibility(View.GONE);
                    rl_background.setVisibility(View.GONE);
                    findViewById(R.id.select_write_characteristic).setVisibility(View.GONE);
                    findViewById(R.id.select_notify_characteristic).setVisibility(View.GONE);
                    findViewById(R.id.select_read_characteristic).setVisibility(View.GONE);
                }
                break;
        }
        return true;
    }


    void checkNetWorkState() {
        ConnectivityManager connMgr = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
        //WiFi是否连接
        NetworkInfo networkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
        boolean isWifiConn = networkInfo.isConnected();
        if (isWifiConn) {
            ed_wifiname.setText(mWifiManager.getConnectionInfo().getSSID());
        }
    }


    @Override
    protected void onDestroy() {
        BusManager.getBus().unregister(this);
        resetTask();
        super.onDestroy();
    }

    /**
     * 根据GATT服务显示该服务下的所有特征值
     *
     * @param gattServices GATT服务
     * @return
     */
    private SimpleExpandableListAdapter displayGattServices(final List<BluetoothGattService> gattServices) {
        if (gattServices == null) return null;
        String uuid;
        final String unknownServiceString = getResources().getString(R.string.unknown_service);
        final String unknownCharaString = getResources().getString(R.string.unknown_characteristic);
        final List<Map<String, String>> gattServiceData = new ArrayList<>();
        final List<List<Map<String, String>>> gattCharacteristicData = new ArrayList<>();

        mGattServices = new ArrayList<>();
        mGattCharacteristics = new ArrayList<>();

        // Loops through available GATT Services.
        for (final BluetoothGattService gattService : gattServices) {
            final Map<String, String> currentServiceData = new HashMap<>();
            uuid = gattService.getUuid().toString();
            currentServiceData.put(LIST_NAME, GattAttributeResolver.getAttributeName(uuid, unknownServiceString));
            currentServiceData.put(LIST_UUID, uuid);
            gattServiceData.add(currentServiceData);

            final List<Map<String, String>> gattCharacteristicGroupData = new ArrayList<>();
            final List<BluetoothGattCharacteristic> gattCharacteristics = gattService.getCharacteristics();
            final List<BluetoothGattCharacteristic> charas = new ArrayList<>();

            // Loops through available Characteristics.
            for (final BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
                charas.add(gattCharacteristic);
                final Map<String, String> currentCharaData = new HashMap<>();
                uuid = gattCharacteristic.getUuid().toString();
                currentCharaData.put(LIST_NAME, GattAttributeResolver.getAttributeName(uuid, unknownCharaString));
                currentCharaData.put(LIST_UUID, uuid);
                gattCharacteristicGroupData.add(currentCharaData);
                if(uuid.contains("FED5")||uuid.contains("fed5")){

                    BluetoothDeviceManager.getInstance().bindChannel(mDevice, PropertyType.PROPERTY_WRITE, gattService.getUuid(), gattCharacteristic.getUuid(), null);
                    BluetoothDeviceManager.getInstance().bindChannel(mDevice, PropertyType.PROPERTY_NOTIFY, gattService.getUuid(), gattCharacteristic.getUuid(), null);
                    BluetoothDeviceManager.getInstance().registerNotify(mDevice, false);
                    BluetoothDeviceManager.getInstance().bindChannel(mDevice, PropertyType.PROPERTY_INDICATE, gattService.getUuid(), gattCharacteristic.getUuid(), null);
                    BluetoothDeviceManager.getInstance().registerNotify(mDevice, true);
                }else if(uuid.contains("FEC8")||uuid.contains("fec8")){
                    BluetoothDeviceManager.getInstance().bindChannel(mDevice, PropertyType.PROPERTY_READ, gattService.getUuid(), gattCharacteristic.getUuid(), null);
                    BluetoothDeviceManager.getInstance().read(mDevice);
                }
            }

            mGattServices.add(gattService);
            mGattCharacteristics.add(charas);
            gattCharacteristicData.add(gattCharacteristicGroupData);
        }

        final SimpleExpandableListAdapter gattServiceAdapter = new SimpleExpandableListAdapter(this, gattServiceData, android.R.layout
                .simple_expandable_list_item_2, new String[]{LIST_NAME, LIST_UUID}, new int[]{android.R.id.text1, android.R.id.text2},
                gattCharacteristicData, android.R.layout.simple_expandable_list_item_2, new String[]{LIST_NAME, LIST_UUID}, new
                int[]{android.R.id.text1, android.R.id.text2});
        return gattServiceAdapter;
    }

    private void showReadInfo(String uuid, byte[] dataArr) {
        mGattUUID.setText(uuid != null ? uuid : getString(R.string.no_data));
        mGattUUIDDesc.setText(GattAttributeResolver.getAttributeName(uuid, getString(R.string.unknown)));
        mDataAsArray.setText(HexUtil.encodeHexStr(dataArr));
        mDataAsString.setText(new String(dataArr));
    }

    private void showDefaultInfo() {
        mGattUUID.setText(R.string.no_data);
        mGattUUIDDesc.setText(R.string.no_data);
        mDataAsArray.setText(R.string.no_data);
        mDataAsString.setText(R.string.no_data);
        mInput.setText(mSpCache.get(WRITE_DATA_KEY + mDevice.getAddress(), ""));
        mOutput.setText("");
        ((EditText) findViewById(R.id.show_write_characteristic)).setText(mSpCache.get(WRITE_CHARACTERISTI_UUID_KEY + mDevice.getAddress(), ""));
        ((EditText) findViewById(R.id.show_notify_characteristic)).setText(mSpCache.get(NOTIFY_CHARACTERISTIC_UUID_KEY + mDevice.getAddress(), ""));
        mOutputInfo = new StringBuilder();
    }

    private void clearUI() {
        mGattUUID.setText(R.string.no_data);
        mGattUUIDDesc.setText(R.string.no_data);
        mDataAsArray.setText(R.string.no_data);
        mDataAsString.setText(R.string.no_data);
        mInput.setText("");
        mOutput.setText("");
        ((EditText) findViewById(R.id.show_write_characteristic)).setText("");
        ((EditText) findViewById(R.id.show_notify_characteristic)).setText("");
        mOutputInfo = new StringBuilder();
        simpleExpandableListAdapter = null;
        mSpCache.remove(WRITE_CHARACTERISTI_UUID_KEY + mDevice.getAddress());
        mSpCache.remove(NOTIFY_CHARACTERISTIC_UUID_KEY + mDevice.getAddress());
        mSpCache.remove(WRITE_DATA_KEY + mDevice.getAddress());
    }

    /**
     * 显示GATT服务展示的信息
     */

    private void showGattServices() {
        if (simpleExpandableListAdapter == null) {
            return;
        }
        final AlertDialog.Builder builder = new AlertDialog.Builder(DeviceControlActivity.this);
        View view = LayoutInflater.from(DeviceControlActivity.this).inflate(R.layout.item_gatt_services, null);
        ExpandableListView expandableListView = view.findViewById(R.id.dialog_gatt_services_list);
        expandableListView.setAdapter(simpleExpandableListAdapter);
        builder.setView(view);
        final AlertDialog dialog = builder.show();
        expandableListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
            @Override
            public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
                dialog.dismiss();
                final BluetoothGattService service = mGattServices.get(groupPosition);
                final BluetoothGattCharacteristic characteristic = mGattCharacteristics.get(groupPosition).get(childPosition);
                final int charaProp = characteristic.getProperties();
                if ((charaProp & BluetoothGattCharacteristic.PROPERTY_WRITE) > 0) {
                    mSpCache.put(WRITE_CHARACTERISTI_UUID_KEY + mDevice.getAddress(), characteristic.getUuid().toString());
                    ((EditText) findViewById(R.id.show_write_characteristic)).setText(characteristic.getUuid().toString());
                    BluetoothDeviceManager.getInstance().bindChannel(mDevice, PropertyType.PROPERTY_WRITE, service.getUuid(), characteristic.getUuid(), null);
                } else if ((charaProp & BluetoothGattCharacteristic.PROPERTY_READ) > 0) {
                    BluetoothDeviceManager.getInstance().bindChannel(mDevice, PropertyType.PROPERTY_READ, service.getUuid(), characteristic.getUuid(), null);
                    BluetoothDeviceManager.getInstance().read(mDevice);
                }
                if ((charaProp & BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
                    mSpCache.put(NOTIFY_CHARACTERISTIC_UUID_KEY + mDevice.getAddress(), characteristic.getUuid().toString());
                    ((EditText) findViewById(R.id.show_notify_characteristic)).setText(characteristic.getUuid().toString());
                    BluetoothDeviceManager.getInstance().bindChannel(mDevice, PropertyType.PROPERTY_NOTIFY, service.getUuid(), characteristic.getUuid(), null);
                    BluetoothDeviceManager.getInstance().registerNotify(mDevice, false);
                } else if ((charaProp & BluetoothGattCharacteristic.PROPERTY_INDICATE) > 0) {
                    mSpCache.put(NOTIFY_CHARACTERISTIC_UUID_KEY + mDevice.getAddress(), characteristic.getUuid().toString());
                    ((EditText) findViewById(R.id.show_notify_characteristic)).setText(characteristic.getUuid().toString());
                    BluetoothDeviceManager.getInstance().bindChannel(mDevice, PropertyType.PROPERTY_INDICATE, service.getUuid(), characteristic.getUuid(), null);
                    BluetoothDeviceManager.getInstance().registerNotify(mDevice, true);
                }
                return true;
            }
        });
    }

    private boolean isHexData(String str) {
        if (str == null) {
            return false;
        }
        char[] chars = str.toCharArray();
        if ((chars.length & 1) != 0) {//个数为奇数，直接返回false
            return false;
        }
        for (char ch : chars) {
            if (ch >= '0' && ch <= '9') continue;
            if (ch >= 'A' && ch <= 'F') continue;
            if (ch >= 'a' && ch <= 'f') continue;
            return false;
        }
        return true;
    }


    /**
     * 追加设备基础信息
     *f
     * @param adapter
     * @param device
     */
    private void appendDeviceInfo(final MergeAdapter adapter, final BluetoothLeDevice device) {
        final TextView tvName = findViewById(R.id.deviceName);
        final TextView tvAddress = findViewById(R.id.deviceAddress);
        final TextView tvClass = findViewById(R.id.deviceClass);
        final TextView tvMajorClass =findViewById(R.id.deviceMajorClass);
        final TextView tvServices = findViewById(R.id.deviceServiceList);
        final TextView tvBondingState =findViewById(R.id.deviceBondingState);

        tvName.setText(device.getName());
        tvAddress.setText(device.getAddress());
        tvClass.setText(device.getBluetoothDeviceClassName());
        tvMajorClass.setText(device.getBluetoothDeviceMajorClassName());
        tvBondingState.setText(device.getBluetoothDeviceBondState());

        final String supportedServices;
        if (device.getBluetoothDeviceKnownSupportedServices().isEmpty()) {
            supportedServices = getString(R.string.no_known_services);
        } else {
            final StringBuilder sb = new StringBuilder();

            for (final BluetoothServiceType service : device.getBluetoothDeviceKnownSupportedServices()) {
                if (sb.length() > 0) {
                    sb.append(", ");
                }

                sb.append(service);
            }
            supportedServices = sb.toString();
        }

        tvServices.setText(supportedServices);
    }
}
